import base64
import io
import os
import json
import re
import sys
import time
import random
import subprocess

import requests
from push import pusher
from logzero import logger
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from selenium.common.exceptions import WebDriverException, TimeoutException


def init_browser(driver="./msedgedriver") -> webdriver.Edge:
    """
    获取浏览器对象
    :param driver:
    :return:
    """
    edge_options = Options()
    # 在服务器上以 root 运行，必须--no-sandbox
    edge_options.add_argument("--headless")
    edge_options.add_argument("--no-sandbox")
    edge_options.add_argument(
        "user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36 Edg/99.0.1150.39")
    # edge_options.add_experimental_option('excludeSwitches', ['enable-automation'])

    try:
        browser = webdriver.Edge(driver, options=edge_options)
        # 躲避检测
        with open('./stealth.min.js') as f:
            js = f.read()
        browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": js})
    except WebDriverException as error:
        logger.error(f"浏览器错误{error}")
    else:
        return browser


def get_qrcode(browser: webdriver.Edge) -> str:
    """
    获取登录的二维码(base64)
    :param browser:
    :return:
    """
    browser.get("https://login.tmall.com/")
    browser.switch_to.frame("J_loginIframe")
    browser.find_element(By.CLASS_NAME, "icon-qrcode").click()
    for _ in range(10):
        # 判断二维码是否存在
        if browser.find_element(By.CLASS_NAME, "qrcode-img").is_displayed():
            logger.info("成功获取到登录二维码")
            time.sleep(1)
            return browser.execute_script("return document.evaluate('//canvas', document).iterateNext().toDataURL()")
        else:
            time.sleep(1)
    raise TimeoutException


def get_sku_ids(item_id: str):
    """
    获取具体的种类
    :param item_id:
    :return:
    """
    try:
        cmd = f"""curl 'https://detail.tmall.com/item.htm?id={item_id}' \
                  -H 'cookie: t={hash(time.time())}' \
                  --compressed"""
        run = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=-1)
        stream_stdout = io.TextIOWrapper(run.stdout, encoding='gbk')
        html = stream_stdout.buffer.read().decode("gbk")
        res = re.compile(r'\"skuList\":([\s\S]*),"defSelected"', re.DOTALL)
        return json.loads(res.findall(html)[0])
    except:
        logger.warning("获取失败，可能是 itemid 有误")
        return []


def get_sgcookie(browser) -> str:
    """
    获取sgcookie
    :param browser:
    :return:
    """
    try:
        WebDriverWait(browser, 60).until(EC.presence_of_element_located((By.CLASS_NAME, 'j_Username')))
    except TimeoutException:
        logger.error("获取超时")
    else:
        for _ in browser.get_cookies():
            if _["name"] == "sgcookie":
                browser.delete_all_cookies()
                return _["value"]
    logger.error("获取cookie失败")


def __get_header(sgcookie):
    return {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.62",
        "Referer": "https://detail.tmall.com/",
        "Cookie": f"sgcookie={sgcookie}"
    }


def __get_detail_param(item_id):
    """
    获取 Detail Param
    :param item_id:
    :return:
    """
    return {
        "itemId": item_id,
        "itemGmtModified": str(time.time_ns() // 1000000),
        "callback": "onMdskip"
    }


def get_model(item_id, cookies):
    item_detail = "https://mdskip.taobao.com/core/initItemDetail.htm"
    try:
        res = requests.get(url=item_detail, params=__get_detail_param(item_id), headers=__get_header(cookies))
        logger.info("正在获取库存信息")
        return json.loads(res.text.split("\n")[-1][1:-1])["defaultModel"]
    except:
        logger.error("Cookie过期请及时更新！")
        raise Exception(f"{cookies},错误")


def mon(_item_id, _sku_id, _name="", t=20):
    global cookies
    qua = 0
    while True:
        try:
            read_cookie()
            ck = random.choice(cookies)
            res = get_model(_item_id, ck)
        except:
            logger.warning(f"{ck}失效！")
            cookies.remove(ck)
            save_cookie()
            continue
        try:
            _ = res["inventoryDO"]["skuQuantity"][_sku_id]["quantity"]
            logger.info(
                f"{_name}\t[id:({_sku_id})][价格:({res['itemPriceResultDO']['priceInfo'][_sku_id]['price']})]库存：{_}")
            if _ > 0 and _ != qua:
                qua = _
                pusher(
                    f"{_name}库存：{qua}\n[价格:({res['itemPriceResultDO']['priceInfo'][_sku_id]['price']})]\nid:({_sku_id})\n{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")
                time.sleep(random.randint(t, 2 * t))
            else:
                time.sleep(random.randint(t, 4 * t))
                continue
        except:
            logger.info(f"sku_id：{_sku_id}不正确")
            break


def read_cookie():
    global cookies

    _cookies = open("COOKIE").readlines()
    cookies = []
    for _c in _cookies:
        _c = _c.replace("\n", "")
        if _c != "":
            cookies.append(_c)
    logger.info(f"当前cookie数量：{len(cookies)}")


def save_cookie():
    global cookies
    with open("COOKIE", "w") as f:
        f.write("\n".join(cookies))
    if len(cookies) < 5:
        pusher(f"COOKIES不足！{len(cookies)}")


if __name__ == '__main__':
    if os.name != "posix":
        logger.error("未授权的用户")
        exit()
    cookies = []
    read_cookie()
    if len(cookies) == 0:
        logger.error("没有cookie")
        exit(0)
    if len(cookies) < 5:
        logger.warning("你的COOKIE数量比较少，可能会被很快封禁！")
    if len(sys.argv) > 2:
        item_id = sys.argv[1]
        sku_id = sys.argv[2]
    else:
        item_id = input("请输入item_id:")
        sku_id = input("请输入sku_id:")
    try:
        for _ in get_sku_ids(item_id):
            if _["skuId"] == sku_id:
                name = _["names"]
        mon(item_id, sku_id, name)
    except Exception as err:
        logger.error("skuid错误，没有这个型号！", err)
